import { connect } from 'dva';
import * as THREE from 'three'
import { useEffect, useRef } from 'react';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'

 const RaycasterPage = (props) => {
   const sceneRef = useRef(null)
   const cameraRef = useRef(null)
   const rendererRef = useRef(null)
   const guiRef = useRef(null)
   const width = 1000; //宽度
   const height = 800; //高度
   useEffect(()=>{
    init()
   }, [])
   const init = () => {
      // 0.添加GUI
      const eventObj = {
        Fullscreen: function(){
         document.body.requestFullscreen()
        },
        Exitscreen: () => {
          document.exitFullscreen()
        }
      }
      guiRef.current = new GUI()
      guiRef.current.add(eventObj, "Fullscreen").name('全屏')
      guiRef.current.add(eventObj, "Exitscreen").name('退出全屏')

      // 1.创建3D场景对象Scene
      sceneRef.current = new THREE.Scene();

      // 4.创建几何体、模型
      setGeometry()

      // 2. 定义虚拟相机部分
      setCamera()

      // 5. 坐标辅助器
      const axesHelper = new THREE.AxesHelper(500)
      sceneRef.current.add(axesHelper)

      // 3.渲染器
      setRenderer()
      // 设置个全局背景
      sceneRef.current.background = new THREE.Color(0xcccccc)

      // 全屏 rendererRef.current.domElement.requestFullscreen()
      window.addEventListener("resize",()=>{
        rendererRef.current.setSize(window.innerWidth,window.innerHeight);
        cameraRef.current.aspect = window.innerWidth/window.innerHeight;
        cameraRef.current.updateProjectionMatrix()
      })

   }

   // 创建相机
   const setCamera = () => {
      // width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
      cameraRef.current = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
      // 实例化一个透视投影相机对象
      // 根据需要设置相机位置具体值
      cameraRef.current.position.set(25, 25, 25);
      cameraRef.current.lookAt(0,5,0);//指向mesh对应的位置
   }
   // 创建几何体、模型
   const setGeometry = () => {
     // 画3个球
     getSphereGeometry()
   }
   // 创建渲染器
   const setRenderer = () => {
      // 创建渲染器对象
      rendererRef.current = new THREE.WebGLRenderer();
      rendererRef.current.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
      rendererRef.current.render(sceneRef.current, cameraRef.current); //执行渲染操作
      document.getElementById('webgl').appendChild(rendererRef.current.domElement);
      // 6. 轨道控制器
      const controls = new OrbitControls(cameraRef.current, rendererRef.current.domElement)

      function animate(){
        requestAnimationFrame(animate)
        controls.update() 
        // mesh.rotation.x += 0.01;
        // mesh.rotation.y += 0.01;
        rendererRef.current.render(sceneRef.current, cameraRef.current)
      }
      animate()
   }
  // 圆柱
   const getSphereGeometry = () => {
    const sphere1 = new THREE.Mesh(
         new THREE.SphereGeometry(1,32,32),
         new THREE.MeshBasicMaterial({color: 0x00ff00})
    )
    const sphere2 = new THREE.Mesh(
        new THREE.SphereGeometry(1,32,32),
        new THREE.MeshBasicMaterial({color: 0x002aff})
    )
    const sphere3 = new THREE.Mesh(
        new THREE.SphereGeometry(1,32,32),
        new THREE.MeshBasicMaterial({color: 0xff0059})
    )
    sphere1.position.set(-3, 2, 1)
    sphere2.position.set(3, -2, -1)
    sphere3.position.set(0, 0, 2)
    sceneRef.current.add(sphere1);
    sceneRef.current.add(sphere2);
    sceneRef.current.add(sphere3);

    // 创建射线
    const raycaster =  new THREE.Raycaster();
    // 创建鼠标向量 二维
    const mouse = new THREE.Vector2();
    document.getElementById('webgl').addEventListener('click',(event)=>{
        //鼠标点击坐标
        const px = event.offsetX;
        const py = event.offsetY;
        //转化坐标
        mouse.x = (px / width)*2-1;
        mouse.y = -((py / height)*2-1);
        //获取射线交点（通过摄像机与鼠标位置更新射线）
        raycaster.setFromCamera(mouse, cameraRef.current)
        // 检测和射线相交的模型（计算物体和射线的焦点）
        const intersects = raycaster.intersectObjects([sphere1,sphere2,sphere3])
        console.log(intersects)
        if(intersects.length > 0){
            if(intersects[0].object._isSelect){
                intersects[0].object.material.color.set(intersects[0].object._originColor)
                intersects[0].object._isSelect = false;
                return
            }
            intersects[0].object._isSelect = true;
            // getHex这样可以获取一个16进制字符串，不然直接改color对象属性，引用不变，originColor也会跟着改变
            intersects[0].object._originColor = intersects[0].object.material.color.getHex();
            intersects[0].object.material.color.set(0xff0000)
        }
    })

    // 设置一个大的包围盒
    let box = new THREE.Box3();
    // 获取大的包围盒
    const arrSphere = [sphere1, sphere2, sphere3];
    for(let i = 0;i<arrSphere.length;i++){
        // //获取每个物体包围盒
        // arrSphere[i].geometry.computeBoundingBox();
        // // 获取包围盒
        // let box3 = arrSphere[i].geometry.boundingBox;
        // // 更新世界矩阵
        // arrSphere[i].updateWorldMatrix(true,true)
        // // 更新包围盒
        // box3.applyMatrix4(arrSphere[i].matrixWorld)

         /**
         * 方法二：直接获取物体的包围盒（不需要世界矩阵转化，也不需要计算）
         */
        let box3 = new THREE.Box3().setFromObject(arrSphere[i])
        // 合并包围盒
        box.union(box3)  
        
       
    }
    let boxHelper = new THREE.Box3Helper(box, 0xffff00);
    sceneRef.current.add(boxHelper);
   }

  return (
    <div>
      <h1 style={{margin: '10px 0'}}>Raycaster射线</h1>
      <div id="webgl" style={{marginTop: 10,marginLeft: 10}}></div>
    </div>
  );
}
export default connect(({common})=>({
  userInfo: common.userInfo,
}))(RaycasterPage)